package main

import (
	"encoding/json"
	"fmt"
	"iotcloud/data"
	"iotcloud/north/api"
	"iotcloud/south/mqtt"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

func main() {
	// 创建IoT南向服务实例，连接到MQTT代理服务器
	southbound := mqtt.NewSouthboundService("tcp://172.168.3.114:1883")

	// 初始化北向API服务器
	apiServer, err := api.NewAPIServer(":8080", "mongodb://localhost:27017")
	if err != nil {
		log.Printf("Failed to initialize northbound API server: %v, will continue without API server\n", err)
	}

	// 如果API服务器初始化成功，初始化管理员用户
	if apiServer != nil {
		if err := apiServer.InitializeAdminUser(); err != nil {
			log.Printf("Failed to initialize admin user: %v\n", err)
		}
	}

	// 启动南向服务
	if err := southbound.Start(); err != nil {
		log.Printf("Failed to start southbound service: %v, will continue with simulation\n", err)
	}
	defer southbound.Stop()

	// 启动北向API服务器
	if apiServer != nil {
		go func() {
			if err := apiServer.Start(); err != nil {
				log.Printf("Northbound API server error: %v\n", err)
			}
		}()
	}

	// 初始化数据服务
	dataService, err := data.NewDataService(data.DataServiceConfig{
		KafkaBrokers:    []string{"localhost:9092"},  // 默认的Kafka端口
		MongoURI:        "mongodb://localhost:27017", // 默认的MongoDB连接字符串
		MongoDBName:     "iotcloud",
		MongoCollection: "device_data",
	})
	if err != nil {
		log.Printf("Failed to initialize data service: %v, will continue with simulation\n", err)
	} else {
		// 启动数据服务
		if err := dataService.Start(); err != nil {
			log.Printf("Failed to start data service: %v\n", err)
		}
		defer dataService.Stop()

		// 注册数据处理函数，将设备数据转发给数据服务
		southbound.RegisterHandler("devices/+/data", func(topic string, payload []byte) {
			// 从主题中提取设备ID
			var deviceID string
			fmt.Sscanf(topic, "devices/%s/data", &deviceID)

			// 处理数据
			if dataService != nil {
				err := dataService.HandleDeviceData(deviceID, topic, payload)
				if err != nil {
					log.Printf("Failed to process device data: %v\n", err)
				}
			}

			log.Printf("Custom handler received message on topic %s: %s\n", topic, payload)
		})
	}

	// 模拟设备连接和数据上报
	go simulateDevices(southbound)

	// 等待中断信号以优雅地关闭服务
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	<-sigChan

	log.Println("Shutting down IoT southbound service and data service...")
}

// simulateDevices 模拟设备连接和数据上报
func simulateDevices(southbound *mqtt.SouthboundService) {
	// 模拟一些设备
	devices := []string{"device-1", "device-2", "device-3"}

	var wg sync.WaitGroup

	// 模拟设备上线
	for _, deviceID := range devices {
		wg.Add(1)
		go func(id string) {
			defer wg.Done()
			// 模拟设备连接
			southbound.HandleDeviceConnect(fmt.Sprintf("devices/%s/connect", id), nil)
		}(deviceID)
	}

	// 为每个设备创建一个goroutine来模拟数据上报
	for _, deviceID := range devices {
		wg.Add(1)
		go func(id string) {
			defer wg.Done()

			// 模拟设备定期上报数据
			for i := 0; i < 10; i++ { // 只模拟10次数据上报
				// 构建模拟数据
				data := map[string]interface{}{
					"temperature": 25.0 + float64(time.Now().UnixNano()%1000)/100.0 - 5.0,
					"humidity":    60.0 + float64(time.Now().UnixNano()%2000)/100.0 - 10.0,
					"status":      "ok",
				}

				// 转换为JSON
				payload, _ := json.Marshal(data)

				// 直接调用处理函数来模拟消息接收
				southbound.HandleDeviceData(fmt.Sprintf("devices/%s/data", id), payload)

				// 每隔5秒上报一次数据
				time.Sleep(5 * time.Second)
			}

			// 模拟设备下线
			southbound.HandleDeviceDisconnect(fmt.Sprintf("devices/%s/disconnect", id), nil)
		}(deviceID)
	}

	// 模拟向设备发送命令
	go func() {
		for i := 0; i < 3; i++ { // 只模拟3轮命令发送
			for _, deviceID := range devices {
				// 检查设备状态
				status, exists := southbound.GetDeviceStatus(deviceID)
				if exists && status == "online" {
					// 发送读取配置命令
					cmdParams := map[string]interface{}{
						"interval": 10,
					}
					err := southbound.SendCommand(deviceID, "read_config", cmdParams)
					if err != nil {
						log.Printf("Failed to send command to device %s: %v\n", deviceID, err)
					}
				}
			}
			// 每隔10秒发送一次命令
			time.Sleep(10 * time.Second)
		}
	}()

	wg.Wait()
}
